package cn.samler.diandi.api.handler;

import cn.samler.diandi.api.model.io.request.pub.Point;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.WKBReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedTypes(Point.class)
@Slf4j
public class GeoPointTypeHandler extends BaseTypeHandler<Point> {
    private int srid = 0;
    WKBReader wkbReader;

    public GeoPointTypeHandler() {
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), srid);
        wkbReader = new WKBReader(geometryFactory);
    }

    public GeoPointTypeHandler(int srid) {
        this.srid = srid;

        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), srid);
        wkbReader = new WKBReader(geometryFactory);
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Point point, JdbcType jdbcType) throws SQLException {

    }

    @Override
    public Point getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return transform(resultSet.getBytes(s));
    }

    @Override
    public Point getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return transform(resultSet.getBytes(i));
    }

    @Override
    public Point getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return transform(callableStatement.getBytes(i));
    }

    private Point transform(byte[] bytes) {
        if (bytes == null)
            return null;

        try {
            byte[] geomBytes = ByteBuffer.allocate(bytes.length - 4).order(ByteOrder.LITTLE_ENDIAN).put(bytes, 4, bytes.length - 4).array();
            Geometry geometry = wkbReader.read(geomBytes);
            com.vividsolutions.jts.geom.Point point = (com.vividsolutions.jts.geom.Point) geometry;
            Point p = new Point();
            p.setLat(point.getX());
            p.setLng(point.getY());
            return p;
        } catch (Exception e) {
            log.warn("point transform failure: " + e);
        }

        return null;
    }

}
